package com.htthorizon.powersupply.async;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.htthorizon.powersupply.domain.RdsGridTgCurDf;
import com.htthorizon.powersupply.domain.RdsGridTgVoltDf;
import com.htthorizon.powersupply.domain.TgLoadMonitor;
import com.htthorizon.powersupply.service.RdsGridTgCurDfService;
import com.htthorizon.powersupply.service.RdsGridTgPowerDfService;
import com.htthorizon.powersupply.service.RdsGridTgVoltDfService;
import com.htthorizon.powersupply.service.TgLoadMonitorService;
import com.htthorizon.powersupply.utils.ApiUtil;
import com.htthorizon.powersupply.utils.OrgUtil;
import com.htthorizon.powersupply.utils.PageUtil;
import com.htthorizon.powersupply.utils.TimeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Component
@Slf4j
public class ApiScheduling {

    @Autowired
    private RdsGridTgPowerDfService rdsGridTgPowerDfService;
    @Autowired
    private RdsGridTgVoltDfService rdsGridTgVoltDfService;
    @Autowired
    private RdsGridTgCurDfService rdsGridTgCurDfService;

    @Autowired
    private TgLoadMonitorService tgLoadMonitorService;

    @Autowired
    private ApiUtil apiUtil;

    @Scheduled(cron = "0 5/15 * * * ?")
    public void schedule() {
        log.info("开始计算单相重负载.....");
        // 等待两个API都完成后进行计算
        CompletableFuture<Void> allFutures = CompletableFuture
                .allOf(CompletableFuture.runAsync(this::fetchApiVoltData)
                        , CompletableFuture.runAsync(this::fetchApiCurData));

        CompletableFuture<Boolean> resultFuture = allFutures.thenApply(v -> calculate());

        // 处理计算结果
        resultFuture.thenAccept(result -> {
            log.info("结算单相电压结果:{}", result);
        }).exceptionally(ex -> {
            log.error("计算过程中出现异常: ", ex);
            return null;
        });
        log.info("结束计算单相重负载.....");
    }


    /**
     * @return API的响应内容
     */
    public void fetchApiVoltData() {
        try {
            Integer total = apiUtil.getGridTgVoltDfTotalNum("1", "10");
            log.info("同步电压数据开始:{}", total);
            if (total > 0) {
                String dateDt = DatePattern.PURE_DATE_FORMAT.format(new Date());
                LambdaQueryWrapper<RdsGridTgVoltDf> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(RdsGridTgVoltDf::getDataDt, dateDt);
                rdsGridTgVoltDfService.remove(queryWrapper);
                PageUtil<RdsGridTgVoltDf, Integer> realTimePowerOutageIntegerPageUtil = new PageUtil<>(total, 2000);
                List<PageUtil.Page<RdsGridTgVoltDf, Integer>> pages = realTimePowerOutageIntegerPageUtil.buildPage();
                for (PageUtil.Page<RdsGridTgVoltDf, Integer> page : pages) {
                    List<RdsGridTgVoltDf> realTimePowerOutage = apiUtil.getGridTgVoltDf(page.getPageNum().toString(), page.getPageSize().toString());
                    rdsGridTgVoltDfService.saveBatch(realTimePowerOutage);
                }
            }
            log.info("同步电压结束");
        } catch (Exception e) {
            log.error("获取电流异常", e);
        }
    }

    public void fetchApiCurData() {
        try {
            Integer total = apiUtil.getGridTgCurDfTotalNum("1", "10");
            if (total > 0) {
                log.info("同步电流开始:{}", total);
                String dateDt = DatePattern.PURE_DATE_FORMAT.format(new Date());
                LambdaQueryWrapper<RdsGridTgCurDf> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(RdsGridTgCurDf::getDataDt, dateDt);
                rdsGridTgCurDfService.remove(queryWrapper);
                PageUtil<RdsGridTgCurDf, Integer> realTimePowerOutageIntegerPageUtil = new PageUtil<>(total, 2000);
                List<PageUtil.Page<RdsGridTgCurDf, Integer>> pages = realTimePowerOutageIntegerPageUtil.buildPage();
                for (PageUtil.Page<RdsGridTgCurDf, Integer> page : pages) {
                    List<RdsGridTgCurDf> realTimePowerOutage = apiUtil.getGridTgCurDf(page.getPageNum().toString(), page.getPageSize().toString());
                    rdsGridTgCurDfService.saveBatch(realTimePowerOutage);
                }
                log.info("同步电流结束:{}");
            }
        } catch (Exception e) {
            log.error("获取电流异常", e);
        }
    }


    boolean calculate() {
        //计算低电压
        log.info("计算成片低电压开始");
        rdsGridTgVoltDfService.compute();
        log.info("计算成片低电压结束");
        log.info("计算单相负载率开始");
        computeLoadFactor();
        log.info("计算单相负载率结束");
        return true;
    }

    public void computeLoadFactor() {
        compute(1, new ArrayList<>(), new ArrayList<>());
    }

    public void compute(int page, List<RdsGridTgVoltDf> votList, List<RdsGridTgCurDf> curList) {
        Page<RdsGridTgVoltDf> rdsGridTgVoltDfPage = getRdsGridTgVoltDf(page, votList);
        List<RdsGridTgVoltDf> voltRecords = rdsGridTgVoltDfPage.getRecords();
        votList.addAll(voltRecords);


        Page<RdsGridTgCurDf> rdsGridTgCurDfPage = getRdsGridTgCurDf(page, curList);
        List<RdsGridTgCurDf> curRecords = rdsGridTgCurDfPage.getRecords();
        curList.addAll(curRecords);

        Map<String, List<RdsGridTgVoltDf>> voltMeterMap = votList.stream().collect(Collectors.groupingBy(RdsGridTgVoltDf::getMeterId));
        Map<String, List<RdsGridTgCurDf>> curMeterMap = curList.stream().collect(Collectors.groupingBy(RdsGridTgCurDf::getMeterId));

        voltMeterMap.forEach((k, v) -> curMeterMap.forEach((kk, vv) -> {
            //meterId相同
            if (k.equals(kk)) {
                if (v.size() == 3 && vv.size() == 3) {
                    //表示都有三相电流电压
                    v.forEach((gridTgVoltDf) -> {
                        vv.forEach((gridTgCurDf) -> {
                            if (gridTgVoltDf.getPhaseFlg().equals(gridTgCurDf.getPhaseFlg())) {
                                String phase = "";
                                if ("1".equals(gridTgVoltDf.getPhaseFlg())) {
                                    phase = "A";
                                } else if ("2".equals(gridTgVoltDf.getPhaseFlg())) {
                                    phase = "B";
                                } else if ("3".equals(gridTgVoltDf.getPhaseFlg())) {
                                    phase = "C";
                                } else {
                                    log.error("相位错误:{}", gridTgVoltDf.getPhaseFlg());
                                    phase = "--";
                                }
                                String tgCapStr = gridTgCurDf.getTgCap();
                                RdsGridTgVoltDf rdsGridTgVoltDf = v.get(0);
                                String timeFormat = DateUtil.format(DateUtil.date(), "yyyy-MM-dd");
                                List<TgLoadMonitor> tgLoadMonitors = new ArrayList<>(97);
                                double tgCap = Double.parseDouble(tgCapStr);
                                String tgType = rdsGridTgVoltDf.getTgType();

                                LambdaQueryWrapper<TgLoadMonitor> tgLoadMonitorQueryWrapper = new LambdaQueryWrapper<>();
                                tgLoadMonitorQueryWrapper.eq(TgLoadMonitor::getMeterId, k);
                                tgLoadMonitorQueryWrapper.in(TgLoadMonitor::getLoadType,"A相过载","A相重载","A相预重载","B相过载","B相重载","B相预重载","C相过载","C相重载","C相预重载");
                                tgLoadMonitorQueryWrapper.eq(TgLoadMonitor::getDataDt, rdsGridTgVoltDf.getDataDt());
                                tgLoadMonitorService.remove(tgLoadMonitorQueryWrapper);


                                //计算96个时间点
                                for (int i = 1; i <= 96; i++) {
                                    JSONObject jsonObjectGridTgVoltDf = new JSONObject(gridTgVoltDf);
                                    Object voltObjVal = jsonObjectGridTgVoltDf.get("val" + i);
                                    JSONObject jsonObjectGridTgCurDf = new JSONObject(gridTgCurDf);
                                    Object curObjVal = jsonObjectGridTgCurDf.get("val" + i);
                                    if (voltObjVal != null && curObjVal != null) {
                                        double volt_val_i = Double.parseDouble((String) voltObjVal);
                                        double cur_val_i = Double.parseDouble((String) curObjVal);
                                        double reuslt = ((3 * volt_val_i * cur_val_i) / (1000 * tgCap)*100);
                                        String loadType = getLoadType(reuslt);
                                        if (reuslt >= 100) {
                                            loadType = phase + "相过载";
                                        } else if (reuslt >= 80) {
                                            loadType = phase + "相重载";
                                        } else if (reuslt >= 70) {
                                            loadType = phase + "相预重载";
                                        }
                                        if (reuslt >= 70) {
                                            TgLoadMonitor tgLoadMonitor = new TgLoadMonitor();
                                            BeanUtils.copyProperties(rdsGridTgVoltDf, tgLoadMonitor, "id");
                                            tgLoadMonitor.setLoadType(loadType);
                                            tgLoadMonitor.setTime(i);
                                            tgLoadMonitor.setStdCountyOrgNm(OrgUtil.map(tgLoadMonitor.getStdCountyOrgNm()));
                                            tgLoadMonitor.setLoadFactor(NumberUtil.round(reuslt, 2) + "%");
                                            tgLoadMonitor.setApperTime(timeFormat + " " + TimeUtil.getTimeByIndex(i));
                                            tgLoadMonitor.setSign(rdsGridTgPowerDfService.sign(rdsGridTgVoltDf.getMeterId()));
                                            tgLoadMonitor.setLabel(rdsGridTgPowerDfService.label(rdsGridTgVoltDf.getMeterId()));
                                            tgLoadMonitor.setTgType(tgType);
                                            tgLoadMonitors.add(tgLoadMonitor);
                                        }
                                    }
                                }
                                tgLoadMonitorService.saveBatch(tgLoadMonitors);
                            }
                        });
                    });
                }
            }
        }));

        if (rdsGridTgVoltDfPage.hasNext() && rdsGridTgCurDfPage.hasNext()) {
            page++;
            compute(page, votList, curList);
        }
    }

    public Page<RdsGridTgVoltDf> getRdsGridTgVoltDf(int page, List<RdsGridTgVoltDf> list) {
        int pageSie = 1000;
        String dataDt = DatePattern.PURE_DATE_FORMAT.format(new Date());
        QueryWrapper<RdsGridTgVoltDf> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("data_dt", dataDt);
        queryWrapper.orderByAsc("meter_id");
        Page<RdsGridTgVoltDf> rdsGridTgVoltDfPage = new Page<>(page, pageSie);
        Page<RdsGridTgVoltDf> result = rdsGridTgVoltDfService.page(rdsGridTgVoltDfPage, queryWrapper);
        return result;
    }

    public Page<RdsGridTgCurDf> getRdsGridTgCurDf(int page, List<RdsGridTgCurDf> list) {
        int pageSie = 1000;
        String dataDt = DatePattern.PURE_DATE_FORMAT.format(new Date());
        QueryWrapper<RdsGridTgCurDf> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("data_dt", dataDt);
        queryWrapper.orderByAsc("meter_id");
        Page<RdsGridTgCurDf> rdsGridTgVoltDfPage = new Page<>(page, pageSie);
        Page<RdsGridTgCurDf> result = rdsGridTgCurDfService.page(rdsGridTgVoltDfPage, queryWrapper);

        return result;
    }


    private String getLoadType(double reuslt) {
        if (reuslt >= 100) {
            return "单相过载";
        } else if (reuslt >= 80) {
            return "单相重载";
        } else if (reuslt >= 70) {
            return "单相预重载";
        }
        return "";
    }
}
